package com.fary.chapter01_aqs.ext_condition;

import com.fary.chapter01_aqs.ext_reentrantLock.FaryReentrantLock;
import lombok.SneakyThrows;

public class TestFaryCondition {

    /**
     *
     * condition.await();
     * 1.当前线程被中断，抛出异常
     * 2.加入等待队列，清除尾部节点waitState!=Condition的节点，说明已经被激活
     * 3.lastWaiter.nextWaiter=node
     * 4.释放锁（state=0，ownerThread=null），并唤醒锁池队列的节点
     * 5.自旋挂起，判断当前节点是否在锁池队列中，不存在就会阻塞，存在则退出循环
     * 6.false：waitState=Condition或者上一个节点为null(刚刚持有锁)
     * 7.true：判断节点的下个节点是否存在，如果存在则表明当前节点已加入到阻塞队列中。
     * 8.自旋，从尾节点开始找，直到头结点
     *
     * condition.signal();
     * 1.判断当前线程是不是持有锁的线程，不是的话就抛异常
     * 2.自旋，修改waitState=0，修改失败继续自旋
     * 3.修改成功，自旋加在锁池尾节点，如果尾节点被取消了，直接唤醒
     */
    public static void main(String[] args) {

        FaryReentrantLock reentrantLock = new FaryReentrantLock();
        FaryCondition condition = reentrantLock.newCondition();

        new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                reentrantLock.lock();
                reentrantLock.lock();
                condition.await();
                System.out.println(Thread.currentThread().getName());
                reentrantLock.unlock();
                reentrantLock.unlock();
            }
        }).start();

        new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                reentrantLock.lock();
                condition.await();
                System.out.println(Thread.currentThread().getName());
                reentrantLock.unlock();
            }
        }).start();

        new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                reentrantLock.lock();
                condition.signal();
                System.out.println(Thread.currentThread().getName());
                reentrantLock.unlock();
            }
        }).start();

        new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                reentrantLock.lock();
                condition.signal();
                System.out.println(Thread.currentThread().getName());
                reentrantLock.unlock();
            }
        }).start();
    }
}
